﻿//Created by Action Script Viewer - http://www.buraks.com/asv
package Engine.Managers {
    import Engine.Classes.*;
    import flash.events.*;
    import Engine.Events.*;
    import flash.display.*;
    import flash.utils.*;
    import __AS3__.vec.*;
    import com.adobe.net.*;
    import Engine.*;
    import flash.errors.*;

    public class LoadingManager implements IEventDispatcher {

        public static const PRIORITY_NORMAL:int = 0;
        public static const PRIORITY_HIGH:int = 1;
        public static const PRIORITY_LOW:int = 2;

        public static var maxLoads:int = 8;
        public static var maxLoadsPerDomain:int = 2;
        public static var logSampleRate:int = 0;
        private static var m_loadingCount:int = 0;
        private static var m_loadQueue:Array = [];
        private static var m_instance:LoadingManager;
        private static var m_outstandingRequests:Dictionary = new Dictionary();
        private static var m_domainMap:Dictionary = new Dictionary();
        private static var m_requestsStarted:int = 0;
        private static var m_requestsReceived:int = 0;
        private static var m_bytesLoaded:Number = 0;
        private static var m_objectsStarted:int = 0;
        private static var m_objectsLoaded:int = 0;
        private static var m_objectsFailed:int = 0;
        private static var m_queueStart:Number = 0;
        private static var m_lastQueueEmptyTime:Number = 0;
        private static var m_worldLoaded:Boolean = false;
        private static var m_useAssetPacks:Boolean = false;
        private static var m_trackLoadTiming:Boolean = false;
        private static var m_trackedLoadRequests:Dictionary = new Dictionary();
        private static var m_trackedLoadTimes:Vector.<Number> = new Vector.<Number>();
;
        private static var m_trackedLoadStartTime:Number = 0;
        private static var m_startedLoading:Boolean = false;
        private static var m_finishedLoading:Boolean = false;
        private static var m_lowPriorityCount:int = 0;

        private var m_dispatcher:EventDispatcher = null;

        public function LoadingManager():void{
            this.m_dispatcher = new EventDispatcher(this);
        }
        public static function getOutstandingRequests():Dictionary{
            return (m_outstandingRequests);
        }
        public static function clearAll():void{
            var _local1:ResourceLoader;
            if (m_outstandingRequests != null){
                for each (_local1 in m_outstandingRequests) {
                    _local1.stopLoad();
                    _local1.removeEventListener(Event.COMPLETE, onComplete);
                    _local1.removeEventListener(IOErrorEvent.IO_ERROR, onError);
                };
            };
            m_domainMap = new Dictionary();
            m_outstandingRequests = new Dictionary();
            m_loadQueue = [];
            m_requestsStarted = 0;
            m_requestsReceived = 0;
            m_loadingCount = 0;
            m_bytesLoaded = 0;
            m_objectsStarted = 0;
            m_objectsLoaded = 0;
            m_objectsFailed = 0;
            m_queueStart = 0;
            m_lastQueueEmptyTime = 0;·
            m_worldLoaded = false;
            m_useAssetPacks = false;
            m_trackLoadTiming = false;
        }
        public static function getInstance():LoadingManager{
            if (m_instance == null){
                m_instance = new (LoadingManager)();
            };
            return (m_instance);
        }
        public static function getObjectsStarted():int{
            return (m_objectsStarted);
        }
        public static function getObjectsLoaded():int{
            return (m_objectsLoaded);
        }
        public static function getObjectsFailed():int{
            return (m_objectsFailed);
        }
        public static function getQueueEmptyTime():Number{
            return (m_lastQueueEmptyTime);
        }
        public static function getBytesLoaded():Number{
            return (m_bytesLoaded);
        }
        public static function startWorldLoad():void{
            if (!m_startedLoading){
                m_startedLoading = true;
                if (GlobalEngine.engineOptions.sendLoadingManagerStats == true){
                    StatsManager.count("d1_drop", "assetsLoading_begun", int(Math.min(((getTimer() - GlobalEngine.startingWaitTime) / 1000), Constants.D1DROP_STATS_MAX_TIMESTAMP)).toString());
                };
            };
        }
        public static function get worldLoaded():Boolean{
            return (m_worldLoaded);
        }
        public static function set worldLoaded(_arg1:Boolean):void{
            m_worldLoaded = _arg1;
        }
        public static function get useAssetPacks():Boolean{
            return (m_useAssetPacks);
        }
        public static function set useAssetPacks(_arg1:Boolean):void{
            m_useAssetPacks = _arg1;
        }
        public static function get trackLoadTiming():Boolean{
            return (m_trackLoadTiming);
        }
        public static function set trackLoadTiming(_arg1:Boolean):void{
            if ((((m_trackLoadTiming === true)) && ((_arg1 === true)))){
                throw (new Error("Already tracking load times"));
            };
            m_trackLoadTiming = _arg1;
            if (m_trackLoadTiming === true){
                m_trackedLoadStartTime = GlobalEngine.currentTime;
                m_trackedLoadRequests = new Dictionary();
                m_trackedLoadTimes = new Vector.<Number>();
            };
        }
        public static function load(_arg1:String, _arg2:Function=null, _arg3:int=0, _arg4:Function=null):Loader{
            return ((loadFromUrl(_arg1, {
                completeCallback:_arg2,
                priority:_arg3,
                faultCallback:_arg4,
                resourceLoaderClass:ResourceLoader
            }) as Loader));
        }
        public static function loadFromUrl(_arg1:String, _arg2:Object=null){
            var _local4:Function;
            var _local5:Function;
            var _local6:int;
            var _local7:Class;
            var _local8:Boolean;
            var _local9:ResourceLoader;
            var _local10:String;
            var _local11:String;
            var _local12:Date;
            var _local3:* = null;
            if (((!((_arg1 == null))) && (!((_arg1 == ""))))){
                logLoadRequest(_arg1);
                if (m_loadingCount == 0){
                    _local12 = new Date();
                    m_queueStart = _local12.getTime();
                };
                m_objectsStarted++;
                _local4 = null;
                _local5 = null;
                _local6 = PRIORITY_NORMAL;
                _local7 = ResourceLoader;
                _local8 = true;
                if (_arg1.indexOf("qlogo.cn/") > 0){
                    _local8 = false;
                };
                if (_arg2){
                    if (_arg2.completeCallback){
                        _local4 = _arg2.completeCallback;
                    };
                    if (_arg2.priority){
                        _local6 = _arg2.priority;
                    };
                    if (_arg2.faultCallback){
                        _local5 = _arg2.faultCallback;
                    };
                    if (((!((_arg2.resourceLoaderClass == null))) && ((_arg2.resourceLoaderClass is Class)))){
                        _local7 = _arg2.resourceLoaderClass;
                    };
                };
                _local9 = null;
                _local10 = null;
                _local11 = null;
                if (((useAssetPacks) && (AssetUrlManager.instance.isPackedResource(_arg1)))){
                    _local11 = AssetUrlManager.instance.lookupPackedResourceUrl(_arg1);
                    _local10 = AssetUrlManager.instance.lookUpUrl(_arg1);
                    _local9 = new PackedResourceLoader(_local11, _local10, _local6, _local4, _local5);
                } else {
                    _local10 = AssetUrlManager.instance.lookUpUrl(_arg1);
                    _local9 = new _local7(_local10, _local6, _local4, _local5);
                };
                if (!_local8){
                    _local9.overridePolicy();
                };
                _local3 = _local9.getLoader();
                addToQueue(_local9, _arg1, _local6);
            } else {
                throw (new Error("NULL url passed to loader!"));
            };
            return (_local3);
        }
        protected static function logLoadRequest(_arg1:String):void{
            var _local2:URI;
            if (logSampleRate > 0){
                _local2 = new URI(_arg1);
                StatsManager.sample(logSampleRate, "assets", _local2.path, !(worldLoaded).toString());
            };
        }
        protected static function addToQueue(_arg1:ResourceLoader, _arg2:String, _arg3:int):void{
            if (trackLoadTiming){
                addTrackedLoad(_arg1, _arg2);
            };
            if (PRIORITY_LOW == _arg3){
                m_lowPriorityCount++;
                m_loadQueue.splice(0, 0, _arg1);
                if (m_loadingCount <= 0){
                    pumpQueue();
                };
            } else {
                if (PRIORITY_HIGH == _arg3){
                    m_loadQueue.push(_arg1);
                    pumpQueue();
                } else {
                    m_loadQueue.splice(m_lowPriorityCount, 0, _arg1);
                    pumpQueue();
                };
            };
        }
        public static function cancelLoad(_arg1:EventDispatcher):void{
            var _local3:ResourceLoader;
            var _local2:int;
            while (_local2 < m_loadQueue.length) {
                _local3 = (m_loadQueue[_local2] as ResourceLoader);
                if (_local3 != null){
                    if (_arg1 == _local3.getLoader()){
                        m_loadQueue.splice(_local2, 1);
                        _local3.stopLoad();
                        checkQueueEmpty();
                        break;
                    };
                };
                _local2++;
            };
        }
        private static function canLoadFromDomain(_arg1:ResourceLoader):Boolean{
            var _local2:String = _arg1.getDomain();
            var _local3:String = _arg1.getURL();
            var _local4:Object = m_domainMap[_local2];
            if ((((_local4 == null)) || ((_local4.count < maxLoadsPerDomain)))){
                return (true);
            };
            if (_arg1.isPackedResource()){
                if (((!((_local4.urls[_local3] == null))) && ((_local4.urls[_local3] > 0)))){
                    return (true);
                };
            };
            return (false);
        }
        private static function addLoadFromDomain(_arg1:ResourceLoader):void{
            var _local2:String = _arg1.getDomain();
            var _local3:String = _arg1.getURL();
            if (m_domainMap[_local2] == null){
                m_domainMap[_local2] = {
                    count:0,
                    urls:new Dictionary()
                };
            };
            if (m_domainMap[_local2].urls[_local3] == null){
                m_domainMap[_local2].urls[_local3] = 0;
            };
            if ((((m_domainMap[_local2].urls[_local3] == 0)) || (!(_arg1.isPackedResource())))){
                m_domainMap[_local2].count++;
            };
            var _local4 = m_domainMap[_local2].urls;
            var _local5 = _local3;
            var _local6 = (_local4[_local5] + 1);
            _local4[_local5] = _local6;
        }
        private static function clearLoadFromDomain(_arg1:ResourceLoader):void{
            var _local2:String = _arg1.getDomain();
            var _local3:String = _arg1.getURL();
            if (m_domainMap[_local2] != null){
                var _local4 = m_domainMap[_local2].urls;
                var _local5 = _local3;
                var _local6 = (_local4[_local5] - 1);
                _local4[_local5] = _local6;
                if (m_domainMap[_local2].urls[_local3] == 0){
                    delete m_domainMap[_local2].urls[_local3];
                    m_domainMap[_local2].count--;
                } else {
                    if (!_arg1.isPackedResource()){
                        m_domainMap[_local2].count--;
                    };
                };
            };
        }
        protected static function pumpQueue():void{
            var queueIdx:* = 0;
            var resourceLoader:* = null;
            var failedToQueue:* = false;
            while ((((((m_loadQueue.length > 0)) && ((m_loadingCount < maxLoads)))) && ((failedToQueue == false)))) {
                failedToQueue = true;
                queueIdx = (m_loadQueue.length - 1);
                while (queueIdx >= 0) {
                    resourceLoader = (m_loadQueue[queueIdx] as ResourceLoader);
                    if (canLoadFromDomain(resourceLoader)){
                        try {
                            m_loadQueue.splice(queueIdx, 1);
                            m_loadingCount++;
                            addLoadFromDomain(resourceLoader);
                            if (resourceLoader.getPriority() != PRIORITY_LOW){
                                m_requestsStarted++;
                            } else {
                                m_lowPriorityCount--;
                            };
                            m_outstandingRequests[resourceLoader] = resourceLoader;
                            resourceLoader.addEventListener(Event.COMPLETE, onComplete, false, 0, true);
                            resourceLoader.addEventListener(IOErrorEvent.IO_ERROR, onError, false, 0, true);
                            resourceLoader.startLoad();
                        } catch(error:IOError) {
                            GlobalEngine.log("Loader", ("IOError occured: " + error.message));
                            m_loadingCount--;
                            clearLoadFromDomain(resourceLoader);
                        };
                        failedToQueue = false;
                        break;
                    };
                    queueIdx = (queueIdx - 1);
                };
            };
            checkQueueEmpty();
        }
        public static function isQueueEmpty():Boolean{
            return ((((((m_loadingCount == 0)) && (!((m_queueStart == 0))))) && ((m_loadQueue.length == 0))));
        }
        protected static function checkQueueEmpty():void{
            var _local1:Date;
            if ((((((m_loadingCount == 0)) && (!((m_queueStart == 0))))) && ((m_loadQueue.length == 0)))){
                _local1 = new Date();
                m_lastQueueEmptyTime = (_local1.getTime() - m_queueStart);
                GlobalEngine.log("Loader", (("Load queue empty, took " + m_lastQueueEmptyTime) + "ms"));
                getInstance().dispatchEvent(new LoaderEvent(LoaderEvent.LOAD_QUEUE_EMPTY));
                m_queueStart = 0;
            };
        }
        public static function onComplete(_arg1:Event):void{
            var _local2:ResourceLoader = (_arg1.target as ResourceLoader);
            var _local3:Object = m_outstandingRequests[_local2];
            var _local4:String = _local2.getDomain();
            m_objectsLoaded++;
            m_loadingCount--;
            clearLoadFromDomain(_local2);
            m_bytesLoaded = (m_bytesLoaded + _local2.getbytesTotal());
            _local2.removeEventListener(Event.COMPLETE, onComplete);
            _local2.removeEventListener(IOErrorEvent.IO_ERROR, onError);
            _local2.stopLoad();
            clearTrackedLoad(_local2);
            if (_local3 != null){
                delete m_outstandingRequests[_local2];
                if (_local2.getPriority() != PRIORITY_LOW){
                    m_requestsReceived++;
                    GlobalEngine.log("Loader", ((("Current loading progress: " + m_requestsReceived) + "/") + m_requestsStarted));
                    getInstance().dispatchEvent(new ProgressEvent(ProgressEvent.PROGRESS, false, false, m_requestsReceived, m_requestsStarted));
                    if (m_requestsReceived >= m_requestsStarted){
                        getInstance().dispatchEvent(new LoaderEvent(LoaderEvent.ALL_HIGH_PRIORITY_LOADED));
                        if (!m_finishedLoading){
                            m_finishedLoading = true;
                            if (GlobalEngine.engineOptions.sendLoadingManagerStats == true){
                                StatsManager.count("d1_drop", "assetsLoading_complete", int(Math.min(((getTimer() - GlobalEngine.startingWaitTime) / 1000), Constants.D1DROP_STATS_MAX_TIMESTAMP)).toString());
                            };
                        };
                    };
                } else {
                    if (m_requestsStarted == 0){
                        getInstance().dispatchEvent(new LoaderEvent(LoaderEvent.ALL_HIGH_PRIORITY_LOADED));
                    };
                };
            } else {
                GlobalEngine.log("Loader", ("Loading request not found after complete: " + _arg1));
            };
            var _local5:LoaderEvent = new LoaderEvent(LoaderEvent.LOADED);
            _local5.eventData = _local2.getLoader();
            getInstance().dispatchEvent(_local5);
            pumpQueue();
        }
        public static function onError(_arg1:IOErrorEvent):void{
            var _local2:ResourceLoader = (_arg1.target as ResourceLoader);
            var _local3:Object = m_outstandingRequests[_local2];
            var _local4:String = _local2.getDomain();
            m_objectsFailed++;
            m_loadingCount--;
            clearLoadFromDomain(_local2);
            _local2.stopLoad();
            _local2.removeEventListener(Event.COMPLETE, onComplete);
            _local2.removeEventListener(IOErrorEvent.IO_ERROR, onError);
            clearTrackedLoad(_local2);
            if (_local3 != null){
                delete m_outstandingRequests[_local2];
                if (_local2.getPriority() != PRIORITY_LOW){
                    m_requestsReceived++;
                    GlobalEngine.log("Loader", ((("Current loading progress: " + m_requestsReceived) + "/") + m_requestsStarted));
                    getInstance().dispatchEvent(new ProgressEvent(ProgressEvent.PROGRESS, false, false, m_requestsReceived, m_requestsStarted));
                };
            } else {
                GlobalEngine.log("Loader", ("Loading request not found after error: " + _arg1));
            };
            pumpQueue();
        }
        private static function areTrackedLoadsInProgress():Boolean{
            var _local1:Object;
            for each (_local1 in m_trackedLoadRequests) {
                return (true);
            };
            return (false);
        }
        private static function addTrackedLoad(_arg1:ResourceLoader, _arg2:String):void{
            if (AssetUrlManager.instance.isHashedAsset(_arg2)){
                m_trackedLoadRequests[_arg1] = GlobalEngine.currentTime;
            };
        }
        private static function clearTrackedLoad(_arg1:ResourceLoader):void{
            var duration:* = NaN;
            var totalDuration:* = NaN;
            var median:* = NaN;
            var average:* = NaN;
            var loadTime:* = NaN;
            var loaderEvent:* = null;
            var resourceLoader:* = _arg1;
            if (m_trackedLoadRequests[resourceLoader] !== undefined){
                duration = (GlobalEngine.currentTime - m_trackedLoadRequests[resourceLoader]);
                m_trackedLoadTimes.push(duration);
                delete m_trackedLoadRequests[resourceLoader];
                if (!areTrackedLoadsInProgress()){
                    trackLoadTiming = false;
                    totalDuration = (GlobalEngine.currentTime - m_trackedLoadStartTime);
                    m_trackedLoadTimes = m_trackedLoadTimes.sort(function (_arg1:Number, _arg2:Number):Number{
                        return ((_arg1 - _arg2));
                    });
                    median = m_trackedLoadTimes[int((m_trackedLoadTimes.length / 2))];
                    average = 0;
                    for each (loadTime in m_trackedLoadTimes) {
                        average = (average + loadTime);
                    };
                    average = (average / m_trackedLoadTimes.length);
                    loaderEvent = new LoaderEvent(LoaderEvent.ALL_TRACKED_LOADED);
                    loaderEvent.eventData = {
                        totalLoadTime:totalDuration,
                        medianLoadTime:median,
                        averageLoadTime:average
                    };
                    getInstance().dispatchEvent(loaderEvent);
                };
            };
        }

        public function addEventListener(_arg1:String, _arg2:Function, _arg3:Boolean=false, _arg4:int=0, _arg5:Boolean=false):void{
            this.m_dispatcher.addEventListener(_arg1, _arg2, _arg3, _arg4);
        }
        public function dispatchEvent(_arg1:Event):Boolean{
            return (this.m_dispatcher.dispatchEvent(_arg1));
        }
        public function hasEventListener(_arg1:String):Boolean{
            return (this.m_dispatcher.hasEventListener(_arg1));
        }
        public function removeEventListener(_arg1:String, _arg2:Function, _arg3:Boolean=false):void{
            this.m_dispatcher.removeEventListener(_arg1, _arg2, _arg3);
        }
        public function willTrigger(_arg1:String):Boolean{
            return (this.m_dispatcher.willTrigger(_arg1));
        }

    }
}//package Engine.Managers 
